# This file is licensed under the Apache License v2.0 with LLVM Exceptions.
# See https://llvm.org/LICENSE.txt for license information.
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception

load("@bazel_skylib//rules:expand_template.bzl", "expand_template")
load("//llvm:tblgen.bzl", "gentbl")
load("//llvm:binary_alias.bzl", "binary_alias")
load(
    "//:vars.bzl",
    "LLVM_VERSION",
)

package(
    default_visibility = ["//visibility:public"],
    features = ["layering_check"],
)

licenses(["notice"])

# TODO: Actually compute version info
genrule(
    name = "config_version_gen",
    outs = ["include/lld/Common/Version.inc"],
    cmd = "echo '#define LLD_VERSION_STRING \"{}\"' > $@".format(LLVM_VERSION),
)

genrule(
    name = "vcs_version_gen",
    outs = ["Common/VCSVersion.inc"],
    cmd = "echo '#undef LLD_REVISION' >> $@\n" +
          "echo '#undef LLD_REPOSITORY' >> $@\n",
)

# See https://github.com/bazelbuild/bazel/issues/13803
cc_library(
    name = "vcs_version",
    hdrs = ["Common/VCSVersion.inc"],
    strip_include_prefix = "Common",
)

cc_library(
    name = "Common",
    srcs = [":config_version_gen"] + glob(["Common/*.cpp"]),
    hdrs = glob(["include/lld/Common/*.h"]),
    includes = ["include"],
    deps = [
        ":vcs_version",
        "//llvm:CodeGen",
        "//llvm:Core",
        "//llvm:DebugInfoDWARF",
        "//llvm:IRPrinter",
        "//llvm:Option",
        "//llvm:Support",
        "//llvm:Target",
        "//llvm:TargetParser",
        "//llvm:config",
    ],
)

gentbl(
    name = "elf_options_inc_gen",
    # See https://github.com/bazelbuild/bazel/issues/13803
    strip_include_prefix = "ELF",
    tbl_outs = [(
        "-gen-opt-parser-defs",
        "ELF/Options.inc",
    )],
    tblgen = "//llvm:llvm-tblgen",
    td_file = "ELF/Options.td",
    td_srcs = [
        "//llvm:include/llvm/Option/OptParser.td",
    ],
)

cc_library(
    name = "ELF",
    srcs = glob([
        "ELF/*.cpp",
        "ELF/*.h",
        "ELF/Arch/*.cpp",
    ]),
    includes = ["ELF"],
    textual_hdrs = [
        "ELF/Arch/PPCInsns.def",
    ],
    deps = [
        ":Common",
        ":elf_options_inc_gen",
        "//llvm:AllTargetsAsmParsers",
        "//llvm:AllTargetsCodeGens",
        "//llvm:AllTargetsDisassemblers",
        "//llvm:Analysis",
        "//llvm:BinaryFormat",
        "//llvm:BitReader",
        "//llvm:BitWriter",
        "//llvm:CodeGen",
        "//llvm:Core",
        "//llvm:DebugInfoDWARF",
        "//llvm:Demangle",
        "//llvm:IPO",
        "//llvm:LTO",
        "//llvm:Linker",
        "//llvm:MC",
        "//llvm:Object",
        "//llvm:Option",
        "//llvm:Passes",
        "//llvm:Remarks",
        "//llvm:Support",
        "//llvm:TargetParser",
        "//llvm:TransformUtils",
        "//llvm:config",
        "@llvm_zlib//:zlib",
        "@llvm_zstd//:zstd",
    ],
)

gentbl(
    name = "coff_options_inc_gen",
    # See https://github.com/bazelbuild/bazel/issues/13803
    strip_include_prefix = "COFF",
    tbl_outs = [(
        "-gen-opt-parser-defs",
        "COFF/Options.inc",
    )],
    tblgen = "//llvm:llvm-tblgen",
    td_file = "COFF/Options.td",
    td_srcs = [
        "//llvm:include/llvm/Option/OptParser.td",
    ],
)

cc_library(
    name = "COFF",
    srcs = glob([
        "COFF/*.cpp",
        "COFF/*.h",
    ]),
    includes = ["COFF"],
    deps = [
        ":Common",
        ":coff_options_inc_gen",
        "//llvm:AllTargetsAsmParsers",
        "//llvm:AllTargetsCodeGens",
        "//llvm:AllTargetsDisassemblers",
        "//llvm:Analysis",
        "//llvm:BinaryFormat",
        "//llvm:BitReader",
        "//llvm:BitWriter",
        "//llvm:Core",
        "//llvm:DebugInfo",
        "//llvm:DebugInfoCodeView",
        "//llvm:DebugInfoMSF",
        "//llvm:DebugInfoPDB",
        "//llvm:Demangle",
        "//llvm:IPO",
        "//llvm:LTO",
        "//llvm:LibDriver",
        "//llvm:Linker",
        "//llvm:MC",
        "//llvm:Object",
        "//llvm:Option",
        "//llvm:Support",
        "//llvm:Symbolize",
        "//llvm:Target",
        "//llvm:TargetParser",
        "//llvm:TransformUtils",
        "//llvm:WindowsDriver",
        "//llvm:WindowsManifest",
        "//llvm:config",
    ],
)

gentbl(
    name = "mingw_options_inc_gen",
    tbl_outs = [(
        "-gen-opt-parser-defs",
        "MinGW/Options.inc",
    )],
    tblgen = "//llvm:llvm-tblgen",
    td_file = "MinGW/Options.td",
    td_srcs = [
        "//llvm:include/llvm/Option/OptParser.td",
    ],
)

cc_library(
    name = "MinGW",
    srcs = glob([
        "MinGW/*.cpp",
        "MinGW/*.h",
    ]),
    includes = ["MinGW"],
    deps = [
        ":Common",
        ":mingw_options_inc_gen",
        "//llvm:Option",
        "//llvm:Support",
        "//llvm:TargetParser",
    ],
)

gentbl(
    name = "macho_options_inc_gen",
    # See https://github.com/bazelbuild/bazel/issues/13803
    strip_include_prefix = "MachO",
    tbl_outs = [(
        "-gen-opt-parser-defs",
        "MachO/Options.inc",
    )],
    tblgen = "//llvm:llvm-tblgen",
    td_file = "MachO/Options.td",
    td_srcs = [
        "//llvm:include/llvm/Option/OptParser.td",
    ],
)

cc_library(
    name = "MachO",
    srcs = glob([
        "MachO/**/*.cpp",
        "MachO/**/*.h",
    ]),
    includes = ["MachO"],
    deps = [
        ":Common",
        ":macho_options_inc_gen",
        "//libunwind:unwind_headers_only",
        "//llvm:BinaryFormat",
        "//llvm:BitReader",
        "//llvm:BitWriter",
        "//llvm:Core",
        "//llvm:DebugInfoDWARF",
        "//llvm:Demangle",
        "//llvm:LTO",
        "//llvm:MC",
        "//llvm:ObjCARC",
        "//llvm:Object",
        "//llvm:Option",
        "//llvm:Support",
        "//llvm:TargetParser",
        "//llvm:TextAPI",
        "//llvm:config",
    ],
)

gentbl(
    name = "wasm_options_inc_gen",
    # See https://github.com/bazelbuild/bazel/issues/13803
    strip_include_prefix = "wasm",
    tbl_outs = [(
        "-gen-opt-parser-defs",
        "wasm/Options.inc",
    )],
    tblgen = "//llvm:llvm-tblgen",
    td_file = "wasm/Options.td",
    td_srcs = [
        "//llvm:include/llvm/Option/OptParser.td",
    ],
)

cc_library(
    name = "Wasm",
    srcs = glob([
        "wasm/*.cpp",
        "wasm/*.h",
    ]),
    includes = ["wasm"],
    deps = [
        ":Common",
        ":wasm_options_inc_gen",
        "//llvm:AllTargetsAsmParsers",
        "//llvm:AllTargetsCodeGens",
        "//llvm:BinaryFormat",
        "//llvm:Core",
        "//llvm:Demangle",
        "//llvm:LTO",
        "//llvm:MC",
        "//llvm:Object",
        "//llvm:Option",
        "//llvm:Support",
        "//llvm:TargetParser",
        "//llvm:config",
    ],
)

expand_template(
    name = "lld_main",
    out = "lld-driver.cpp",
    substitutions = {
        "@TOOL_NAME@": "lld",
    },
    template = "//llvm:cmake/modules/llvm-driver-template.cpp.in",
)

cc_binary(
    name = "lld",
    srcs = glob([
        "tools/lld/*.cpp",
        "tools/lld/*.h",
    ]) + ["lld-driver.cpp"],
    deps = [
        ":COFF",
        ":Common",
        ":ELF",
        ":MachO",
        ":MinGW",
        ":Wasm",
        "//llvm:Support",
        "//llvm:TargetParser",
    ],
)

# These are the required names for lld running under different environs.
#
# Unix/Linux require that the binary be named "ld.lld".
# macOS require that the binary be named "ld64.lld".
# Windows require that the binary be named "lld-link".
# WebAssembly builds require that the binary be named "wasm-ld".
[
    binary_alias(
        name = name,
        binary = ":lld",
    )
    for name in [
        "ld.lld",
        "ld64.lld",
        "lld-link",
        "wasm-ld",
    ]
]
